#define IO_TLB_SHIFT 11
/* Width of DMA addresses in the IO TLB. 30 bits is a b44 limitation. */
-#define IO_TLB_DMA_BITS 30
+#define DEFAULT_IO_TLB_DMA_BITS 30
static int swiotlb_force;
static char *iotlb_virt_start;
*/
static DEFINE_SPINLOCK(io_tlb_lock);
+static unsigned int io_tlb_dma_bits = DEFAULT_IO_TLB_DMA_BITS;
+static int __init
+setup_io_tlb_bits(char *str)
+{
+ io_tlb_dma_bits = simple_strtoul(str, NULL, 0);
+ return 0;
+}
+__setup("swiotlb_bits=", setup_io_tlb_bits);
+
static int __init
setup_io_tlb_npages(char *str)
{
int rc = xen_create_contiguous_region(
(unsigned long)iotlb_virt_start + (i << IO_TLB_SHIFT),
get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT),
- IO_TLB_DMA_BITS);
+ io_tlb_dma_bits);
BUG_ON(rc);
}
printk(KERN_INFO "Software IO TLB enabled: \n"
" Aperture: %lu megabytes\n"
- " Kernel range: 0x%016lx - 0x%016lx\n",
+ " Kernel range: 0x%016lx - 0x%016lx\n"
+ " Address size: %u bits\n",
bytes >> 20,
(unsigned long)iotlb_virt_start,
- (unsigned long)iotlb_virt_start + bytes);
+ (unsigned long)iotlb_virt_start + bytes,
+ io_tlb_dma_bits);
}
void
int
swiotlb_dma_supported (struct device *hwdev, u64 mask)
{
- return (mask >= ((1UL << IO_TLB_DMA_BITS) - 1));
+ return (mask >= ((1UL << io_tlb_dma_bits) - 1));
}
EXPORT_SYMBOL(swiotlb_init);
static char opt_badpage[100] = "";
string_param("badpage", opt_badpage);
+/*
+ * Bit width of the DMA heap.
+ */
+unsigned int dma_bitsize = CONFIG_DMA_BITSIZE;
+unsigned long max_dma_mfn = (1UL << (CONFIG_DMA_BITSIZE - PAGE_SHIFT)) - 1;
+static void parse_dma_bits(char *s)
+{
+ unsigned int v = simple_strtol(s, NULL, 0);
+ if ( v >= (sizeof(long)*8 + PAGE_SHIFT) )
+ {
+ dma_bitsize = sizeof(long)*8 + PAGE_SHIFT;
+ max_dma_mfn = ~0UL;
+ }
+ else
+ {
+ dma_bitsize = v;
+ max_dma_mfn = (1UL << (dma_bitsize - PAGE_SHIFT)) - 1;
+ }
+}
+custom_param("dma_bits", parse_dma_bits);
+
/*
* Amount of memory to reserve in a low-memory (<4GB) pool for specific
* allocation requests. Ordinary requests will not fall back to the
* lowmem emergency pool.
*/
-static unsigned long lowmem_emergency_pool_pages;
-static void parse_lowmem_emergency_pool(char *s)
+static unsigned long dma_emergency_pool_pages;
+static void parse_dma_emergency_pool(char *s)
{
unsigned long long bytes;
bytes = parse_size_and_unit(s, NULL);
- lowmem_emergency_pool_pages = bytes >> PAGE_SHIFT;
+ dma_emergency_pool_pages = bytes >> PAGE_SHIFT;
}
-custom_param("lowmem_emergency_pool", parse_lowmem_emergency_pool);
+custom_param("dma_emergency_pool", parse_dma_emergency_pool);
#define round_pgdown(_p) ((_p)&PAGE_MASK)
#define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
#define NR_ZONES 3
#define pfn_dom_zone_type(_pfn) \
- (((_pfn) <= MAX_DMADOM_PFN) ? MEMZONE_DMADOM : MEMZONE_DOM)
+ (((_pfn) <= max_dma_mfn) ? MEMZONE_DMADOM : MEMZONE_DOM)
static struct list_head heap[NR_ZONES][MAX_NUMNODES][MAX_ORDER+1];
if ( curr_free )
init_heap_pages(pfn_dom_zone_type(i), mfn_to_page(i), 1);
}
+
+ printk("Domain heap initialised: DMA width %u bits\n", dma_bitsize);
}
/*
s_tot = round_pgup(ps) >> PAGE_SHIFT;
e_tot = round_pgdown(pe) >> PAGE_SHIFT;
- s_dma = min(s_tot, MAX_DMADOM_PFN + 1);
- e_dma = min(e_tot, MAX_DMADOM_PFN + 1);
+ s_dma = min(s_tot, max_dma_mfn + 1);
+ e_dma = min(e_tot, max_dma_mfn + 1);
if ( s_dma < e_dma )
init_heap_pages(MEMZONE_DMADOM, mfn_to_page(s_dma), e_dma - s_dma);
- s_nrm = max(s_tot, MAX_DMADOM_PFN + 1);
- e_nrm = max(e_tot, MAX_DMADOM_PFN + 1);
+ s_nrm = max(s_tot, max_dma_mfn + 1);
+ e_nrm = max(e_tot, max_dma_mfn + 1);
if ( s_nrm < e_nrm )
init_heap_pages(MEMZONE_DOM, mfn_to_page(s_nrm), e_nrm - s_nrm);
}
if ( unlikely(pg == NULL) &&
((order > MAX_ORDER) ||
(avail_heap_pages(MEMZONE_DMADOM,-1) <
- (lowmem_emergency_pool_pages + (1UL << order)))) )
+ (dma_emergency_pool_pages + (1UL << order)))) )
return NULL;
}
avail_nrm = avail_heap_pages(MEMZONE_DOM,-1);
avail_dma = avail_heap_pages(MEMZONE_DMADOM,-1);
- if ( avail_dma > lowmem_emergency_pool_pages )
- avail_dma -= lowmem_emergency_pool_pages;
+ if ( avail_dma > dma_emergency_pool_pages )
+ avail_dma -= dma_emergency_pool_pages;
else
avail_dma = 0;